﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.ServiceProcess;
using System.Timers;
using Config;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using QueueManagerHelper;
using System.IO;

namespace QueueManagerService
{
    partial class QueueService : ServiceBase
    {

        private Timer _timer = new Timer();
        private QueueSection _settings;
        private QueueMonitor _queueMonitor = null;
        private DateTime _lastTempQueueRun = DateTime.MinValue;
        private double _processingDelayPeriod = 0;

        protected override void OnStart(string[] args)
        {
            string functionName = GetType().ToString() + " OnStart: ";
            Logger.Write(functionName + "Enter", "Trace", 3);
            try
            {
                _processingDelayPeriod = double.Parse(ConfigurationManager.AppSettings.Get("processingdelayperiod"));
                _queueMonitor = new QueueMonitor();
                //Set up all the relevant exchange helpers so that they don't need to be recreated every time
                SetupQueueMonitorExchangeHelpers();
                _timer.Enabled = true;
                _timer.AutoReset = false;
                _timer.Interval = _processingDelayPeriod;  
                _timer.Elapsed += new System.Timers.ElapsedEventHandler(ProcessQueues);
                _timer.Start();
            }
            catch (Exception ex)
            {
                Logger.Write(functionName + "Fatal Exception: Stopping service: " + ex.ToString(), "Fatal Error", 5, 1, System.Diagnostics.TraceEventType.Error );
                Environment.Exit(-1);
            }
            finally
            {
                Logger.Write(functionName + "Exit", "Trace", 3);
            }
        }

        private void SetupIgnoreEmailFrom()
        {
            string functionName = GetType().ToString() + " SetupIgnoreEmailFrom: ";
            Logger.Write(functionName + "Enter", "Trace", 3);
            try
            {
                _queueMonitor.IgnoreEmailFrom = new List<string>();
                string[] emailAddressesToIgnore = File.ReadAllLines(ConfigurationManager.AppSettings.Get("ignoreemailaddresslistlocation"));
                foreach (string address in emailAddressesToIgnore)
                {
                    if (!_queueMonitor.IgnoreEmailFrom.Contains(address.Trim().ToLower()))
                        _queueMonitor.IgnoreEmailFrom.Add(address.Trim().ToLower());
                }
            }
            catch (Exception ex)
            {
                Logger.Write(functionName + "Warning: No emails will be ignored based on from address: " + ex.ToString(), "Warning", 4, 1, System.Diagnostics.TraceEventType.Warning);
                _queueMonitor.IgnoreEmailFrom = new List<string>();
            }
            finally
            {
                Logger.Write(functionName + "Exit", "Trace", 3);
            }
        }

        private void SetupIgnoreWhenSubjectContains()
        {
            string functionName = GetType().ToString() + " SetupIgnoreWhenSubjectContains: ";
            Logger.Write(functionName + "Enter", "Trace", 3);
            try
            {
                _queueMonitor.IgnoreWhenSubjectContains = new List<string>();
                string[] subjectsContainingPhraseToIgnore = File.ReadAllLines(ConfigurationManager.AppSettings.Get("ignoresubjectlistlocation"));
                foreach (string phrase in subjectsContainingPhraseToIgnore)
                {
                    if (!_queueMonitor.IgnoreWhenSubjectContains.Contains(phrase.Trim().ToLower()))
                        _queueMonitor.IgnoreWhenSubjectContains.Add(phrase.Trim().ToLower());
                }
            }
            catch (Exception ex)
            {
                Logger.Write(functionName + "Warning: No emails will be ignored based on words in subject: " + ex.ToString(), "Warning", 4, 1, System.Diagnostics.TraceEventType.Warning);
                _queueMonitor.IgnoreEmailFrom = new List<string>();
            }
            finally
            {
                Logger.Write(functionName + "Exit", "Trace", 3);
            }
        }

        private void SetupQueueMonitorExchangeHelpers()
        {
            string functionName = GetType().ToString() + " SetupQueueMonitorExchangeHelpers: ";
            Logger.Write(functionName + "Enter", "Trace", 3);
            try
            {
                _queueMonitor.ExchangeHelpers = new Dictionary<string, Exchange2007Helper>();
                foreach (QueueSetting queueSettings in _settings.Queues)
                {
                    if (queueSettings.RouteEmailsFromExchange)
                    {
                        Logger.Write(functionName + "Adding ExchangeHelper for queue " + queueSettings.Name + " with Id " + queueSettings.QueueID, "Trace", 1);
                        Exchange2007Helper exchangeHelper = new Exchange2007Helper(ConfigurationManager.AppSettings.Get("exchangeserviceurl"),
                                                                   queueSettings.ExchangeDomain,
                                                                   queueSettings.ExchangeUsername,
                                                                   queueSettings.ExchangePassword);
                        _queueMonitor.ExchangeHelpers.Add(queueSettings.QueueID.ToLower(), exchangeHelper);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Write(functionName + "Error: " + ex.ToString(), "Error", 5, 1, System.Diagnostics.TraceEventType.Error);
                throw;
            }
            finally
            {
                Logger.Write(functionName + "Exit", "Trace", 3);
            }
        }

        public QueueService()
        {
            string functionName = GetType().ToString() + " QueueService: ";
            Logger.Write(functionName + "Enter", "Trace", 3);
            try
            {
                InitializeComponent();
                _settings = (QueueSection)ConfigurationManager.GetSection("queues");
            }
            catch (Exception ex)
            {
                Logger.Write(functionName + "Fatal Exception: Stopping service: " + ex.ToString(), "Fatal Error", 5, 1, System.Diagnostics.TraceEventType.Error );
                Environment.Exit(-1);
            }
            finally
            {
                Logger.Write(functionName + "Exit", "Trace", 3);
            }
        }

        private void ProcessQueues(object sender, System.Timers.ElapsedEventArgs e)
        {
            string functionName = GetType().ToString() + " ProcessQueues: ";
            Logger.Write(functionName + "Enter", "Trace", 3);
            try
            {
                _timer.Stop();
                //Reload ignore list
                SetupIgnoreEmailFrom();
                //Reload list with words in subject which to ignore
                SetupIgnoreWhenSubjectContains();

                foreach (QueueSetting queueSettings in _settings.Queues)
                    _queueMonitor.ProcessQueue(queueSettings);
                _timer.Interval = _processingDelayPeriod; // wait x milliseconds before we start processing again
                _timer.AutoReset = false;
                _timer.Enabled = true;
                _timer.Start();
            }
            catch (Exception ex)
            {
                Logger.Write(functionName + "Fatal Exception: Stopping service: " + ex.ToString(), "Fatal Error", 5, 1, System.Diagnostics.TraceEventType.Error );
                Environment.Exit(-1);
            }
            finally
            {
                Logger.Write(functionName + "Exit", "Trace", 3);
            }
        }
    }
}
